/**
 * @Title: BalanceServiceImpl
 * @Package cn.com.yiqi.wsc.service.balance.impl
 * @Description: TODO
 * Copyright: Copyright (c) 2016
 * Company: 成都壹柒互动科技有限公司
 * @author 会员系统组-胥钰淋
 * @date 2017/3/3 11:23
 * @version V1.0
 */
package cn.com.yiqi.wsc.service.balance.impl;

import cn.com.artemis.framework.service.message.service.yunxin.impl.YunxinSMSServiceImpl;
import cn.com.yiqi.wsc.Ro.BalanceParaDO;
import cn.com.yiqi.wsc.Ro.BalanceRecordVO;
import cn.com.yiqi.wsc.common.Result;
import cn.com.yiqi.wsc.common.ResultStatusEnum;
import cn.com.yiqi.wsc.common.ResultUtil;
import cn.com.yiqi.wsc.dao.balance.BalanceFetchDao;
import cn.com.yiqi.wsc.dao.balance.BalanceRecordDao;
import cn.com.yiqi.wsc.dao.balance.entity.BalanceFetchEntity;
import cn.com.yiqi.wsc.dao.balance.entity.BalanceFetchEntityDTO;
import cn.com.yiqi.wsc.dao.balance.entity.BalanceRecordEntity;
import cn.com.yiqi.wsc.entity.customer.Customer;
import cn.com.yiqi.wsc.enumeration.PointBizType;
import cn.com.yiqi.wsc.enumeration.PointStatus;
import cn.com.yiqi.wsc.service.balance.BalanceService;
import cn.com.yiqi.wsc.service.balance.dataobject.BalanceRecordDO;
import cn.com.yiqi.wsc.service.balance.enumeration.BalanceFetchStatus;
import cn.com.yiqi.wsc.service.balance.enumeration.BalanceType;
import cn.com.yiqi.wsc.service.balance.enumeration.OperateType;
import cn.com.yiqi.wsc.service.customer.CustomerService;
import cn.com.yiqi.wsc.service.point.PointService;
import cn.com.yiqi.wsc.service.point.dataobject.PointOrderDO;
import cn.com.yiqi.wsc.service.sysparams.SysParamsService;
import cn.com.yiqi.wsc.service.weixin.impl.WeixinPayImpl;
import cn.com.yiqi.wsc.util.DateUtil;
import cn.com.yiqi.wsc.util.OrderNoUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author 会员系统组-胥钰淋
 * @ClassName: BalanceServiceImpl
 * @Description: TODO
 * @date 2017/3/3 11:23
 */
@Service
public class BalanceServiceImpl implements BalanceService {

    @Autowired
    private BalanceRecordDao balanceRecordDao;
    @Autowired
    private BalanceFetchDao balanceFetchDao;
    @Autowired
    private PointService pointService;
    @Autowired
    private CustomerService customerService;
    @Autowired
    private SysParamsService sysParamsService;
    @Autowired
    private WeixinPayImpl weixinPay;


    @Autowired
    private YunxinSMSServiceImpl yunxinSMSService;

    @Value("#{APP_PROP['yunxin.sms.fetch.templateId']}")
    private Integer templateId;

    @Transactional
    @Override
    public Result<Boolean> point2Balance(Long customerId, Integer point) {
        Result<Boolean> result = new Result<>();
        Date date = new Date();
        PointOrderDO pointOrderDO = new PointOrderDO();
        pointOrderDO.setCustomerId(customerId);
        pointOrderDO.setTime(date);
        pointOrderDO.setType(PointBizType.exchange_to_balance);
        pointOrderDO.setBizDesc("积分兑换余额");
        pointOrderDO.setPoint(point);
        //直接兑换
        pointOrderDO.setStatus(PointStatus.used);
        Result<Long> pointResult = pointService.point2Balance(pointOrderDO);
        if (null != pointResult.getReturnValue()) {
            BalanceRecordEntity balanceRecordEntity = new BalanceRecordEntity();
            balanceRecordEntity.setBizId(pointResult.getReturnValue());
            balanceRecordEntity.setType(BalanceType.point_to_balance.getValue());
            balanceRecordEntity.setCustomerId(customerId);
            balanceRecordEntity.setDesc("积分兑换余额");
            BigDecimal amount = new BigDecimal(point + "").multiply(sysParamsService.getPointPara().getPointScale());
            balanceRecordEntity.setAmount(amount);
            balanceRecordEntity.setOperateTime(date);
            if (balanceRecordDao.insert(balanceRecordEntity) > 0) {
                // 2017/3/3 更新客户余额
                Customer customer = customerService.selectById(customerId.intValue());
                customer.setBalance(customer.getBalance() == null ? amount : customer.getBalance().add(amount));
                customerService.updateCustomer(customer);
                result.setReturnValue(true);
                ResultUtil.success(result);
            } else {
                result.setReturnValue(false);
                result.setErrMsg("新增余额记录出错");
            }
        } else {
            result.setReturnValue(false);
            result.setErrMsg(pointResult.getErrMsg());
        }
        return result;
    }

    @Transactional
    @Override
    public Result<Boolean> submitFetchRequest(Long customerId, Float amount) {
        Result<Boolean> re = new Result<>();
        BalanceFetchEntity balanceFetchEntity = new BalanceFetchEntity();
        balanceFetchEntity.setCustomerId(customerId);
        balanceFetchEntity.setFetchAmount(new BigDecimal(amount + ""));
        balanceFetchEntity.setRealAmount(new BigDecimal(amount + ""));
        balanceFetchEntity.setApplyTime(new Date());
        balanceFetchEntity.setStatus(BalanceFetchStatus.pending.getValue());
        Integer id = balanceFetchDao.insert(balanceFetchEntity);
        if (id > 0) {
            //余额记录
            BalanceRecordEntity record = new BalanceRecordEntity();
            record.setCustomerId(customerId);
            record.setAmount(new BigDecimal(amount + ""));
            record.setType(BalanceType.point_to_balance.getValue());
            record.setBizId(Long.parseLong(id + ""));
            record.setOperateTime(new Date());
            record.setOperateType(OperateType.DECREASE.getValue());
            record.setDesc("提现");
            balanceRecordDao.insert(record);
            //  2017/3/3 扣除余额
            Customer customer = customerService.selectById(customerId.intValue());
            customer.setBalance(customer.getBalance().multiply(new BigDecimal(amount + "")));
            customerService.updateCustomer(customer);
            re.setReturnValue(true);
            return re;
        }
        re.setReturnValue(false);
        return ResultUtil.fail(re, "系统错误");
    }

    @Override
    public Result<Boolean> passFetchRequest(Long fetchId) {
        Result<Boolean> result = new Result<>();
        BalanceFetchEntity balanceFetchEntity = new BalanceFetchEntity();
        balanceFetchEntity.setId(fetchId);

        //通过fetchId获取 订单号，金额，openId
        BalanceFetchEntityDTO balanceFetchEntityDTO = balanceFetchDao.getFetchInfoByFetchId(fetchId);

        if (balanceFetchEntityDTO == null) {
            return ResultUtil.paramError(result, "数据不存在");
        }

        if (BalanceFetchStatus.pass.getValue() == balanceFetchEntityDTO.getStatus()) {
            return ResultUtil.paramError(result, "已提现");
        }
        //String openId,int amount,String tradeNo,String desc
        String openId = balanceFetchEntityDTO.getOpenId();

        //乘100  元 转化为 分
        int amount = balanceFetchEntityDTO.getFetchAmount().multiply(new BigDecimal(100)).intValue();

        String tradeNo = OrderNoUtil.nextOrderId();
        Result resultPay = weixinPay.transfer("osxB0wlEtZuwThNchfy7wfJYD33M", amount, tradeNo, "余额提现");
        if (ResultUtil.isSuccess(resultPay)) {
            //提现成功
            String transaction_id = (String) resultPay.getData().get("payment_no");


            //修改状态
            balanceFetchEntity.setStatus(BalanceFetchStatus.pass.getValue());
            balanceFetchEntity.setExternalUid(openId);
            balanceFetchEntity.setExternalPayNo(transaction_id);

            balanceFetchDao.update(balanceFetchEntity);

            //发送短信
            if (balanceFetchEntityDTO.getCustomerTel() != null) {

                yunxinSMSService.sendTemplate(templateId, balanceFetchEntityDTO.getCustomerTel(), "[]");
            }

        } else {

            balanceFetchEntity.setStatus(BalanceFetchStatus.submited.getValue());
            balanceFetchDao.update(balanceFetchEntity);
            result.setStatus(ResultStatusEnum.服务器内部错误.getCode());
            result.setErrMsg(resultPay.getErrMsg());
        }

        return result;
    }

    @Override
    public Result<Boolean> notPassFetchRequest(Long fetchId) {
        Result<Boolean> result = new Result<>();

        BalanceFetchEntity balanceFetchEntity = new BalanceFetchEntity();
        balanceFetchEntity.setId(fetchId);

        balanceFetchEntity.setStatus(BalanceFetchStatus.not_pass.getValue());
        //修改状态
        balanceFetchDao.update(balanceFetchEntity);

        return result;
    }

    @Override
    public List<BalanceRecordVO> balanceList(Integer userId) {

        return balanceRecordDao.balanceVoList(userId);
    }

    @Override
    public List<BalanceFetchEntity> selectFetchListByUserId(Integer userId) {
        return balanceFetchDao.selectList(Long.parseLong(userId + ""), null, null, null);
    }


    @Transactional
    @Override
    public Result canWithdraw(Integer userId, BigDecimal balance) {
        Result<Boolean> re = new Result();

        if (balance.compareTo(BigDecimal.ZERO) < 0) {
            return ResultUtil.fail(re, "提现金额不能小于0");
        }
        Customer customer = customerService.selectById(userId);
        if (customer.getVip() == 0) {
            return ResultUtil.fail(re, "您不是vip，不能提现！");
        }
        if (customer.getBalance().compareTo(balance) < 0) {
            return ResultUtil.fail(re, "余额不足");
        }
        if (new BigDecimal(balance + "").compareTo(balance) != 0) {
            return ResultUtil.fail(re, "提现金额必须为整数");
        }
        BalanceParaDO bdo = sysParamsService.getBalancePara();
        if (balance.intValue() % bdo.getPerMin() != 0) {
            return ResultUtil.fail(re, "提现金额必须为" + bdo.getPerMin() + "的整数倍");
        }
        if (balance.intValue() > bdo.getPerMax()) {
            return ResultUtil.fail(re, "单次提现最大金额" + bdo.getPerMax());
        }

        Calendar c = Calendar.getInstance();
        String dateUnit = "";
        if (bdo.getTimeUnit() == 3) {
            c.add(Calendar.MONTH, 0);
            c.set(Calendar.DAY_OF_MONTH, 1);
            dateUnit = "月";
        } else if (bdo.getTimeUnit() == 2) {
            c.add(Calendar.WEEK_OF_YEAR, 0);
            c.set(Calendar.DAY_OF_WEEK, 1);
            dateUnit = "周";
        } else {
            try {
                Date date = DateUtil.stringToDate("yyyy-MM-dd", DateUtil.dateToString("yyyy-MM-dd", new Date()));
                c.setTime(date);
            } catch (Exception e) {

            }
            dateUnit = "天";
        }

        //获取本 月/周/天 已申请记录(时间倒序)
        List<BalanceFetchEntity> list = balanceFetchDao.selectList(Long.parseLong(userId + ""), null, c.getTime(), null);
        if (list.size() >= bdo.getTimes()) {
            return ResultUtil.fail(re, "每" + dateUnit + "最多申请" + bdo.getTimes());
        }
        //两次提现申请间隔(当前时间距本月天数 - 最近一次申请时间距本月天数)
//        if(list.size() > 0){
//            Long days = DateUtils.getFragmentInDays(new Date(),Calendar.MONTH) - DateUtils.getFragmentInDays(list.get(0).getApplyTime(),Calendar.MONTH);
//            if(days < bdo.getInterval()){
//                return ResultUtil.fail(re,"每月提现间隔"+bdo.getInterval()+"本月上次提现申请为"+days+"天前");
//            }
//            //每月最大提现，没有限制
////            BigDecimal mothTotal = BigDecimal.ZERO;
////            for (int i = 0; i < list.size(); i++) {
////                mothTotal.add(list.get(i).getFetchAmount());
////            }
////
////            if(mothTotal.compareTo(balance.add(new BigDecimal(""+bdo.getPerMax()))) > 0){
////                return ResultUtil.fail(re,"每月最多提现"+bdo.getPerMax()+",当前还可提现"+new BigDecimal(""+bdo.getPerMax()).subtract(mothTotal));
////            }
//
//        }
        //申请提现
        re = submitFetchRequest(Long.parseLong(userId + ""), balance.floatValue());
        return re;
    }

    @Override
    public Result withDrawIndex(Integer userId) {
        Result re = new Result();
        Customer customer = customerService.selectById(userId);
        BalanceParaDO bdo = sysParamsService.getBalancePara();
        re.putData("balancePara", bdo);
        re.putData("balance", customer.getBalance());
        BigDecimal totalWithdraw = balanceFetchDao.sumWithDraw(BalanceFetchStatus.completed.getValue(), userId);
        re.putData("totalWithdraw", totalWithdraw);
        //获取本月已申请记录(时间倒序)
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);
        List<BalanceFetchEntity> list = balanceFetchDao.selectList(Long.parseLong(userId + ""), null, c.getTime(), null);
        Integer lastTimes = bdo.getTimes() - list.size();
        re.putData("lastTimes", lastTimes < 0 ? 0 : lastTimes);
        BigDecimal mothTotal = BigDecimal.ZERO;
        for (int i = 0; i < list.size(); i++) {
            mothTotal.add(list.get(i).getFetchAmount());
        }
        return re;
    }

    @Transactional
    @Override
    public Integer CostBalance(BalanceRecordDO bdo) {
        BalanceRecordEntity record = new BalanceRecordEntity();
        record.setDesc(bdo.getDesc());
        record.setCustomerId(bdo.getCustomerId());
        record.setOperateTime(new Date());
        record.setBizId(Long.parseLong(bdo.getBizId() + ""));
        record.setOperateType(OperateType.DECREASE.getValue());
        record.setAmount(bdo.getAmount());
        record.setType(bdo.getType().getValue());
        record.setOperateType(OperateType.DECREASE.getValue());
        balanceRecordDao.insert(record);
        //扣除用户余额
        if (!bdo.getHasDeal()) {
            Customer customer = customerService.selectById(bdo.getCustomerId().intValue());
            customer.setBalance(customer.getBalance().subtract(bdo.getAmount()));
            customerService.updateCustomer(customer);
        }
        return record.getId().intValue();
    }

    @Transactional
    @Override
    public Integer getBalance(BalanceRecordDO bdo) {
        BalanceRecordEntity record = new BalanceRecordEntity();
        record.setDesc(bdo.getDesc());
        record.setCustomerId(bdo.getCustomerId());
        record.setOperateTime(new Date());

        record.setOperateType(OperateType.ADD.getValue());
        record.setAmount(bdo.getAmount());
        record.setType(bdo.getType().getValue());
        balanceRecordDao.insert(record);
        //增加用户余额
        Customer customer = customerService.selectById(bdo.getCustomerId().intValue());
        customer.setBalance(customer.getBalance().add(bdo.getAmount()));
        customerService.updateCustomer(customer);
        return record.getId().intValue();
    }
}
